package cn.starremote.component.utils;

import cn.starremote.component.annotation.ExcelColumn;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;

import java.io.*;
import java.lang.reflect.Field;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Title: CSV 工具类
 * @date 2020/4/24 10:28 上午
 * @author  Wangjw
 */
@Slf4j
public class CsvUtils {


    //CSV文件分隔符
    private final static String NEW_LINE_SEPARATOR="\n";

    /**写入csv文件
     * @param data 数据内容
     * @param filePath 创建的csv文件路径  **/
    public static <T>  void writeCsv(List<T> data, Class<T> cls , String filePath) {

        Field[] fields = cls.getDeclaredFields();
        List<Field> fieldList = Arrays.stream(fields)
                .filter(field -> {
                    ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
                    if (annotation != null && annotation.order() > 0) {
                        field.setAccessible(true);
                        return true;
                    }
                    return false;
                }).sorted(Comparator.comparing(field -> {
                    int col = 0;
                    ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
                    if (annotation != null) {
                        col = annotation.order();
                    }
                    return col;
                })).collect(Collectors.toList());

        /*构建 标题列*/
        List<String> newHead = fieldList.stream().map(field -> field.getAnnotation(ExcelColumn.class).value()).collect(Collectors.toList());

        //初始化 csv format
        CSVFormat format = CSVFormat.DEFAULT.withHeader(newHead.toArray(new String[]{})).withRecordSeparator(NEW_LINE_SEPARATOR);
        File file = new File(filePath);//根据指定的文件名创建File对象
        //判断目标文件所在目录是否存在
        if (!file.getParentFile().exists()){//如果目标文件所在文件夹不存在，则创建父文件夹
            log.info("创建"+file.getName()+"所在目录不存在，正在创建！" );

            //判断父文件夹是否存在，如果存在则表示创建成功，否则失败
            if ( !file.getParentFile().mkdirs() ){
                log.info("创建目标文件所在目录失败！" );
            }
        }
        try(
                Writer writer = new BufferedWriter(
                     new OutputStreamWriter(
                     new FileOutputStream(filePath), "gbk"));
                CSVPrinter printer = new CSVPrinter(writer, format)){
            if(data!=null){
                for (T t : data) {
                    List<String> records = new ArrayList<>();
                    fieldList.forEach(field -> {
                        Class<?> type = field.getType();
                        Object value = "";
                        try {
                            if(t instanceof Map){
                                value = ((Map) t).get(field.getName());
                            }else {
                                value = field.get(t);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        if (value != null) {
                            if (type == Date.class && value instanceof Date) {
                                records.add(DateUtil.format((Date) value,DateUtil.DEFAULT_TIME_FORMAT));
                            } else {
                                String str = String.valueOf(value);
                                str = str.trim();
                                if(isNumeric(str)){
                                    records.add(str + "\t");
                                }else{
                                    records.add(str);
                                }
                            }
                        }else {
                            records.add("\t");
                        }
                    });
                    printer.printRecord(records);
                    printer.flush();
                }
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        System.out.println("CSV文件创建成功,文件路径:"+filePath);
    }


    public static  boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("^-?\\d+(\\.\\d+)?$");//这个也行
        Matcher isNum = pattern.matcher(str);
        if (!isNum.matches()) {
            return false;
        }
        return true;
    }
}